package com.gitee.loyo

import java.lang.reflect.Method
import java.math.BigDecimal
import java.sql.Types
import java.text.SimpleDateFormat
import java.time.*
import java.time.format.DateTimeFormatter
import java.util.*
import kotlin.reflect.KClass
import kotlin.reflect.jvm.kotlinFunction
import kotlin.reflect.safeCast

object Utils {

    fun isNotObject(type: KClass<*>): Boolean{
        return type == Short::class || type == Int::class || type == Long::class
            || type == Float::class || type == Double::class
            || type == String::class || type == Boolean::class
            || type == Date::class || type == LocalDate::class
            || type == LocalTime::class || type == LocalDateTime::class || type == BigDecimal::class
            || type == ByteArray::class
    }

    fun toClass(type: Int): KClass<*>{
        var result: KClass<*> = Any::class
        when (type) {
            Types.CHAR, Types.VARCHAR, Types.LONGVARCHAR -> result = String::class
            Types.NUMERIC, Types.DECIMAL -> result = BigDecimal::class
            Types.BIT -> result = Boolean::class
            Types.TINYINT -> result = Byte::class
            Types.SMALLINT -> result = Short::class
            Types.INTEGER -> result = Int::class
            Types.BIGINT -> result = Long::class
            Types.REAL, Types.FLOAT -> result = Float::class
            Types.DOUBLE -> result = Double::class
            Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY -> result = Array<Byte>::class
            Types.DATE -> result = LocalDate::class
            Types.TIME -> result = LocalTime::class
            Types.TIMESTAMP -> result = LocalDateTime::class
        }
        return result
    }

    fun compareObject(obj1: Any?, obj2: Any?): Boolean {
        return return if(obj1 == null){
            obj2 == null
        }else{
            obj1 == obj2
        }
    }

    fun <T: Any> tryConvert(value: Any, kType: KClass<T>): T {
        return when(value){
            is Short -> when(kType){
                Short::class -> value as T
                Int::class -> value.toInt() as T
                Long::class -> value.toLong() as T
                Float::class -> value.toFloat() as T
                Double::class -> value.toDouble() as T
                String::class -> value.toString() as T
                Boolean::class -> (value.toInt() == 1) as T
                BigDecimal::class -> value.toInt().toBigDecimal() as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is Int -> when(kType){
                Short::class -> value.toShort() as T
                Int::class -> value as T
                Long::class -> value.toLong() as T
                Float::class -> value.toFloat() as T
                Double::class -> value.toDouble() as T
                String::class -> value.toString() as T
                Boolean::class -> (value == 1) as T
                BigDecimal::class -> value.toBigDecimal() as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is Long -> when(kType){
                Short::class -> value.toShort() as T
                Int::class -> value.toInt() as T
                Long::class -> value as T
                Float::class -> value.toFloat() as T
                Double::class -> value.toDouble() as T
                String::class -> value.toString() as T
                Boolean::class -> (value.toInt() == 1) as T
                BigDecimal::class -> value.toBigDecimal() as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is Float -> when(kType){
                Short::class -> value.toInt().toShort() as T
                Int::class -> value.toInt() as T
                Long::class -> value.toLong() as T
                Float::class -> value as T
                Double::class -> value.toDouble() as T
                String::class -> value.toString() as T
                Boolean::class -> (value.toInt() == 1) as T
                BigDecimal::class -> value.toBigDecimal() as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is Double -> when(kType){
                Short::class -> value.toInt().toShort() as T
                Int::class -> value.toInt() as T
                Long::class -> value.toLong() as T
                Float::class -> value.toFloat() as T
                Double::class -> value as T
                String::class -> value.toString() as T
                Boolean::class -> (value.toInt() == 1) as T
                BigDecimal::class -> value.toBigDecimal() as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is String -> when(kType){
                Short::class -> value.toShort() as T
                Int::class -> value.toInt() as T
                Long::class -> value.toLong() as T
                Float::class -> value.toFloat() as T
                Double::class -> value.toDouble() as T
                String::class -> value as T
                Boolean::class -> value.toBoolean() as T
                Date::class -> SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value) as T
                LocalDate::class -> LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd")) as T
                LocalTime::class -> LocalTime.parse(value, DateTimeFormatter.ofPattern("HH:mm:ss")) as T
                LocalDateTime::class -> LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) as T
                BigDecimal::class -> value.toBigDecimal() as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is Boolean -> when(kType){
                String::class -> value.toString() as T
                Boolean::class -> value as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is Date -> when(kType){
                String::class -> SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(value) as T
                Date::class -> value as T
                LocalDate::class -> value.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() as T
                LocalDateTime::class -> value.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is LocalDate -> when(kType){
                String::class -> value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) as T
                Date::class -> Date.from(value.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()) as T
                LocalDate::class -> value as T
                LocalDateTime::class -> value.atStartOfDay() as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is LocalTime -> when(kType){
                String::class -> value.format(DateTimeFormatter.ofPattern("HH:mm:ss")) as T
                LocalTime::class -> value as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is LocalDateTime -> when(kType){
                String::class -> value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) as T
                Date::class -> Date.from(value.atZone(ZoneId.systemDefault()).toInstant()) as T
                LocalDate::class -> value.toLocalDate() as T
                LocalTime::class -> value.toLocalTime() as T
                LocalDateTime::class -> value as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is BigDecimal -> when(kType){
                Short::class -> value.toShort() as T
                Int::class -> value.toInt() as T
                Long::class -> value.toLong() as T
                Float::class -> value.toFloat() as T
                Double::class -> value.toDouble() as T
                String::class -> value.toString() as T
                BigDecimal::class -> value as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            is ByteArray -> when(kType){
                ByteArray::class -> value as T
                else -> throw TypeCastException("${value::class.java.simpleName}($value)无法转换为${kType.java.name}")
            }
            else -> throw TypeCastException("不支持${value::class.java.simpleName}($value)类型的转换")
        }
    }

    fun sign(method: Method): String {
        return "${method.name}(${method.parameters?.joinToString(", ") { "${it.type}" }})"
    }
}